package topoMesh;

import hdgeom.primitives.Vec3D;

import java.util.ArrayList;

import processing.core.PVector;

public class RuleCatmull extends RuleSplit {
	public float extrudeFactorEdge = 0;
	public float extrudeFactorNode = 0;
	public float extrudeFactorFace = 0;

	public TopoMeshNode getNodePt(TopoMeshNode n) {
		if (n.fix) {
			TopoMeshNode node = new TopoMeshNode(n);
			node.fix = n.fix;
			return node;
		}
		ArrayList<TopoMeshFace> nbFaces = n.getFaces();
		Vec3D sumFaces = new Vec3D();
		for (int i = 0; i < nbFaces.size(); i++) {
			TopoMeshFace face = nbFaces.get(i);
			sumFaces.add(this.faceNodes[face.id]);
		}
		sumFaces.div((float) nbFaces.size());
		Vec3D sumEdges = new Vec3D();
		ArrayList<TopoMeshEdge> nbEdges = n.getEdges();
		for (int i = 0; i < nbEdges.size(); i++) {
			TopoMeshEdge edge = nbEdges.get(i);
			sumEdges.add(edge.getCenter());
		}
		sumEdges.mult(2f / nbEdges.size());
		Vec3D sumPos = new Vec3D(n.x, n.y, n.z);
		sumPos.mult(nbEdges.size() - 3);
		Vec3D newPos = new Vec3D();
		newPos.add(sumFaces);
		newPos.add(sumEdges);
		newPos.add(sumPos);
		newPos.div((float) nbEdges.size());

		Vec3D normal = n.getNormal();
		if (Float.isNaN(normal.x)) {
			System.out.println("normal");
			System.out.println("n faces: " + n.getFaces().size());
		} else {
			normal.mult(getNodeExtrude(n) * extrudeFactorNode);
			newPos.add(normal);
		}
		TopoMeshNode node = new TopoMeshNode(newPos);

		node.setComment(n.getComment());
		return node;
	}

	public TopoMeshNode getFacePt(TopoMeshFace face) {
		PVector center = face.getCenter();
		TopoMeshNode node = new TopoMeshNode(center);
		if (!face.fix) {
			if (!node.fix) {
				Vec3D normal = face.getNormal();
				if (!Float.isNaN(normal.x)) {
					normal.mult(getFaceExtrude(face) * extrudeFactorFace);
					node.add(normal);
				}
			}
		} else {
			node.fix = true;
		}
		return node;
	}

	public TopoMeshNode getEdgePt(TopoMeshEdge edge) {
		TopoMeshNode n1 = edge.getNode1();
		TopoMeshNode n2 = edge.getNode2();
		if (n1.fix && n2.fix) {
			TopoMeshNode newNode = new TopoMeshNode(edge.getCenter());
			newNode.fix = true;
			return newNode;
		}
		Vec3D vSum = new Vec3D();
		vSum.add(n1);
		vSum.add(n2);
		int nFace = 0;
		TopoMeshFace face = edge.getFace1();
		if (face != null) {
			nFace++;
			vSum.add(face.getCenter());
		}
		face = edge.getFace2();
		if (face != null) {
			nFace++;
			vSum.add(face.getCenter());
		}
		vSum.div(nFace + 2f);
		Vec3D normal = edge.getNormal();
		if (Float.isNaN(normal.x)) {
			System.out.println("edge normal");
		} else {
			normal.mult(getEdgeExtrude(edge) * extrudeFactorEdge);
			vSum.add(normal);
		}
		TopoMeshNode node = new TopoMeshNode(vSum);
		return node;
	}
}
